<script>
import { addClass, removeClass, hasClass } from '@/utils/index.js'
export default {
  name: 'Edit',
  props: {
    // 配置的字段
    column: {
      type: Object,
      default: () => {}
    },
    // 单条数据信息
    row: {
      type: Object,
      default: () => {}
    },
    // 编辑后的数据
    editRow: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      box: '',
      default: this.column.key + 'Default', // 初始值
      edit: this.column.key + 'Edit', // 是否开启编辑组件
      tag: this.column.key + 'Tag' // 是否改变编辑组件
    }
  },
  computed: {
    // 判断是否可变操作
    isMutable() {
      const { mutable } = this.column.edit
      if (typeof mutable === 'boolean' && !mutable) return false
      return true
    }
  },
  mounted() {
    this.box = this.$el.parentNode.parentNode
    if (!this.box) return
    this.box.addEventListener('mouseover', this.mouseover)
    this.box.addEventListener('mouseout', this.mouseout)
  },
  beforeDestroy() {
    if (!this.box) return
    this.box.removeEventListener('mouseover', this.mouseover)
    this.box.removeEventListener('mouseout', this.mouseout)
  },
  methods: {
    // 移除校验错误的样式
    init() {
      if (hasClass(this.$el, 'error')) removeClass(this.$el, 'error')
    },
    // 鼠标移入
    mouseover(e) {
      if (this.$el) addClass(this.$el, 'show')
    },
    // 鼠标移出
    mouseout(e) {
      if (this.$el) removeClass(this.$el, 'show')
    },
    // 点击编辑
    handleEdit() {
      const { edit, key } = this.column
      if (!edit.type) {
        this.$message.error('请配置可用的组件类型')
        return
      }
      this.editRow[this.default] = this.row[key]
      this.$set(this.editRow, this.edit, true)
      edit.type === 'input' && this.$nextTick(() => {
        this.$refs.editInput.focus()
      })
    },
    // 点击还原
    restore() {
      const { key } = this.column
      this.row[key] = this.editRow[this.default]
      this.$set(this.editRow, this.edit, false)
      this.$set(this.editRow, this.tag, false)
      const isExit = Object.keys(this.editRow).some(e => e.indexOf('Tag') > -1 && e !== this.tag && this.editRow[e])
      if (!isExit) this.$set(this.editRow, 'isRowEdit', false)
    },
    // 设置值
    setValue(e) {
      const { key } = this.column
      this.row[key] = e
      this.editRow[this.tag] = true
      this.editRow.isRowEdit = true
    },
    // 创建节点
    normalizeVnode() {
      let vnode = null
      const { edit, key, dict, title } = this.column
      // 若原始数据无此字段，则新增字段并设置响应式
      switch (edit.type) {
        case 'input': {
          vnode = (
            <el-input
              ref='editInput'
              size='small'
              placeholder={`请输入${title}`}
              value={this.row[key]}
              on={{
                focus: e => {
                  if (hasClass(this.$el, 'error')) removeClass(this.$el, 'error')
                },
                input: e => {
                  this.setValue(e)
                }
              }}
              {...edit.inner}
            >
            </el-input>
          )
          break
        }
        case 'select': {
          const options = require(`@/utils/dictionary/dictionary.js`).default[dict.key]
          let optionVNodes = []
          if (options) {
            optionVNodes = options.map(op => {
              return (
                <el-option value={op.value} label={op.label} key={op.value}/>
              )
            })
          }
          vnode = (
            <el-select
              size='small'
              placeholder={`请选择${title}`}
              value={this.row[key]}
              on={{
                focus: e => {
                  if (hasClass(this.$el, 'error')) removeClass(this.$el, 'error')
                },
                change: e => {
                  this.setValue(e)
                }
              }}
              {...edit.inner}
            >
              {optionVNodes}
            </el-select>
          )
          break
        }
        case 'date': {
          vnode = (
            <el-date-picker
              size='small'
              value={this.row[key]}
              clearable={false}
              ref='editInput'
              type='date'
              placeholder={`请选择${title}`}
              on={{
                focus: e => {
                  if (hasClass(this.$el, 'error')) removeClass(this.$el, 'error')
                },
                input: e => {
                  this.setValue(e)
                }
              }}
              {...edit.inner}
            >
            </el-date-picker>
          )
          break
        }
        default: {
          return this.row[key]
        }
      }
      return vnode
    }
  },
  render(h) {
    this.init()
    return (
      <div class='edit-wrapper'>
        { this.editRow[this.tag] ? <i class='tag' /> : null}
        {
          this.editRow[this.edit] ? <div class='box'>
            { this.editRow.isNewRow ? null : <i class='el-icon-error' onClick={this.restore}></i> }
            { this.normalizeVnode() }
          </div>
            : <div><span class='info'>{ this.$slots.default }</span>
              { this.isMutable ? <i class='el-icon-edit' title='编辑' onClick={this.handleEdit}></i> : null}
            </div>
        }
      </div>
    )
  }
}
</script>

<style lang="less" scoped>
  .edit-wrapper{
    &.show{
      .el-icon-edit,
      .el-icon-error{
        visibility: visible;
      }
    }
    &.error{
      /deep/ .el-input__inner{
        border-color: #f56c6c;
      }
    }
    .box{
      position: relative;
      padding: 6px 3px;
    }
    .el-icon-edit{
      margin-left: 6px;
      color: #2338E4;
      cursor: pointer;
      visibility: hidden;
    }
    .el-icon-error{
      position: absolute;
      right: -2px;
      top: 1px;
      font-size: 18px;
      color: #d1d1d1;
      z-index:1;
      cursor: pointer;
      visibility: hidden;
    }
    .tag{
      position: absolute;
      left: 0;
      top: 0;
      width: 0;
      height: 0;
      border-top: 5px solid red;
      border-left: 5px solid transparent;
      border-right: 5px solid transparent;
      transform: rotate(133deg);
    }
  }
</style>
<style lang="less">
  .config-table{
    .el-tooltip {
      .edit-box{
        .info{
          width: 90%;
          display: inline-block;
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
          vertical-align: middle;
        }
      }
    }
  }
</style>
